package cz.acies.uniql.sql.element;

import java.util.Map;

import org.dom4j.Element;
import org.dom4j.dom.DOMElement;


import cz.acies.uniql.dialect.Dialect;
import cz.acies.uniql.dialect.MySQLDialect;
import cz.acies.uniql.sql.Const;
import cz.acies.uniql.sql.UniQLExpr;
import cz.acies.uniql.utils.UniQLConfig;

/**
 * The Class Column.
 */
public class UniQLColumn extends UniQLExpr
{
	private static final long serialVersionUID = 3557395663623051885L;
	
	private String tableName = null; 
	private String alias = null;
	
	/**
	 * Konstruktor tridy UniQLColumn.
	 */
	public UniQLColumn() {
	}

	/**
	 * Konstruktor tridy column.
	 * 
	 * @param dialect - dialect
	 */
	public UniQLColumn(Dialect dialect) {
		super(dialect);
	}
	
	/**
	 * Konstruktor tridy UniQLColumn.
	 * 
	 * @param columnName - column name
	 */
	public UniQLColumn(String columnName) {
		this("", columnName);
	}

	/**
	 * Konstruktor tridy UniQLColumn.
	 * 
	 * @param tableName - table name
	 * @param columnName - column name
	 */
	public UniQLColumn(String tableName, String columnName) {
		super();
		this.setTableName(tableName);
		this.parse(columnName);
	}
	
	/**
	 * Konstruktor tridy UniQLColumn.
	 * 
	 * @param tableName - table name
	 * @param columnName - column name
	 * @param alias - alias
	 */
	public UniQLColumn(String tableName, String columnName, String alias) {
		super();
		this.setTableName(tableName);
		this.setName(columnName);
		this.setAlias(alias);
	}

	// -----  -----------------------------------------------------------------
		
	/* (non-Javadoc)
	 * @see cz.acies.uniql.sql.UniQLExpr#translate()
	 */
	@Override
	@SuppressWarnings("unchecked")
	public String translate() throws Exception {
		StringBuffer sb = new StringBuffer("");
		String columnName = this.getName();
		Dialect dialect = this.getDialect();
		if (columnName != null && columnName.length() > 0) {
			if (tableName != null && tableName.length() > 0) {
				sb.append(dialect.CTI_LQ())
					.append(tableName.toLowerCase())
					.append(dialect.CTI_RQ())
					.append(Const.DELIMITER);
			}
			if (columnName.equals("*")) {
				sb.append(columnName.toUpperCase());
			} else {
				sb.append(dialect.LQ()).append(columnName.toUpperCase()).append(dialect.RQ());
			}
			if (alias != null && alias.length() > 0) {
				sb.append(" "+Const.ALIAS+" ").append(alias);
			}
		}
		if (UniQLConfig.DEBUG_MODE && (dialect instanceof MySQLDialect)) {
			Map<String, Object> joinIndex = null;
			if (getAliasMap() != null) {
				joinIndex = (Map<String, Object>)getAliasMap().get("joinIndex");
			}
			if (tableName == null && joinIndex != null && !joinIndex.isEmpty()) {
				new Exception("UniQLColumn( "+columnName+" ) has not tableName").printStackTrace(); 
			}
		}	
		return sb.toString();
	}

	/* (non-Javadoc)
	 * @see cz.acies.uniql.sql.UniQLExpr#parse(java.lang.String)
	 */
	public UniQLExpr parse(String expr) {
		int pos = expr.indexOf("."); 
		//String COLUMN_PATTERN = "((\\w+)\\.)?(\\w+)(\\s+[Aa][Ss]\\s+(\\w+))?";
		
		if (pos > 0) {
			String shl = expr.substring(0, pos);
			this.setTableName(shl);
			String shr = expr.substring(pos+1, expr.length());
			pos = shr.toUpperCase().indexOf(" AS ");
			if (pos > 0) {
				shl = shr.substring(0, pos);
				this.setName(shl.trim());
				shr = shr.substring(pos+4, shr.length());
				this.setAlias(shr.trim());
			} else {
				this.setName(shr.trim());
			}
		} else {
			pos = expr.toUpperCase().indexOf(" AS ");
			//System.out.println("pos(1) = "+pos);
			if (pos > 0) {
				String shl = expr.substring(0, pos);
				this.setName(shl.trim());
				String shr = expr.substring(pos+4, expr.length());
				this.setAlias(shr.trim());
			} else {
				this.setName(expr.trim());
			}			
		}
		return this;
	}
	
	// ----- ------------------------------------------------------------------
	
	/* (non-Javadoc)
	 * @see cz.acies.uniql.sql.UniQLExpr#clear()
	 */
	public UniQLExpr clear() {
		super.clear();
		tableName = null; 
		alias = null;
		return this;
	}

	
	/* (non-Javadoc)
	 * @see java.lang.Object#clone()
	 */
	@Override
	public Object clone() throws CloneNotSupportedException {
		Object clone = super.clone();
		assert clone instanceof UniQLColumn;
		((UniQLColumn) clone).setTableName(tableName); 
		((UniQLColumn) clone).setAlias(alias);
		return clone;
	}
	
	// ----- Getter & setter --------------------------------------------------
	
	/**
	 * Nacte hodnotu alias.
	 * 
	 * @return - vraci hodnotu alias
	 */
	public String getAlias() {
		return alias;
	}

	/**
	 * Zadava hodnotu alias.
	 * 
	 * @param alias - alias
	 * 
	 * @return vraci column
	 */
	public UniQLColumn setAlias(String alias) {
		this.alias = alias;
		return this;
	}

	/**
	 * As.
	 * 
	 * @param alias - alias
	 * 
	 * @return vraci column
	 */
	public UniQLColumn as(String alias) {
		this.alias = alias;
		return this;
	}

	/**
	 * Nacte hodnotu table name.
	 * 
	 * @return - vraci hodnotu table name
	 */
	public String getTableName() {
		return tableName;
	}

	/**
	 * Zada hodnotu table name.
	 * 
	 * @param tableName nova hodnota table name
	 */
	public void setTableName(String tableName) {
		this.tableName = tableName;
	}

	// -----  -----------------------------------------------------------------
	
	/* (non-Javadoc)
	 * @see cz.acies.uniql.sql.UniQLExpr#transToXML()
	 */
	public String transToXML() throws Exception {
		DOMElement node = new DOMElement("UniQLColumn");
		transToXML(node);
		return node.asXML();
	}
	
	/* (non-Javadoc)
	 * @see cz.acies.uniql.sql.UniQLExpr#transToXML(org.dom4j.dom.DOMElement)
	 */
	public DOMElement transToXML(DOMElement node) throws Exception {
		String columnName = this.getName();
		node.setName("UniQLColumn");
		if (columnName != null && columnName.length() > 0) { 
			if (tableName != null && tableName.length() > 0) {
				node.setAttribute("table", tableName.toLowerCase());
			}
			if (columnName.equals("*")) {
				node.setAttribute("name", columnName.toUpperCase());
			} else {
				node.setAttribute("name", columnName.toUpperCase());
			}
			if (alias != null && alias.length() > 0) {
				node.setAttribute("alias", alias);
			}
		}
		return node;
	}

	/* (non-Javadoc)
	 * @see cz.acies.uniql.sql.UniQLExpr#xmlToExpr(java.lang.String)
	 */
	public UniQLExpr xmlToExpr(String xml) throws Exception {
		return null;
	}

	/* (non-Javadoc)
	 * @see cz.acies.uniql.sql.UniQLExpr#xmlToExpr(org.dom4j.Element)
	 */
	public UniQLExpr xmlToExpr(Element node) throws Exception {
		String s1 = node.attributeValue("table");
		if (s1 != null && s1.length() > 0) this.setTableName(s1);
		String s2 = node.attributeValue("name");
		if (s2 != null && s2.length() > 0) this.setName(s2);
		String s3 = node.attributeValue("alias");
		if (s3 != null && s3.length() > 0) this.setAlias(s3);
		return this;
	}
	
	// -----  -----------------------------------------------------------------
	
	public String toString() {
		return "UniQLColumn( table="+this.tableName+", colName="+this.getName()+", alias="+this.alias+" )";
	}
	/*
	public int hashCode() {
		int hash = -1; 
		if (this.getName() != null) hash = this.getName().hashCode();
		if (this.getTableName() != null) hash += this.getTableName().hashCode();
		if (this.getAlias() != null) hash += this.getAlias().hashCode();
		return hash; 
	}
	*/
};
